package com.xg.sys.vo;

import com.xg.frame.constant.SysConstant;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.apache.commons.collections.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author tzt
 * @date Created in 2021/8/13 14:21
 * @description：树形展示实体
 * @modified By：
 */
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class TreeVO {
    private String id;
    private String parentId;
    private String name;
    private String resKey;
    private String resUrl;
    private String resType;
    private String resLevel;
    private String description;
    private String icon;
    private Boolean checked;
    private Boolean open;
    private List<TreeVO> children = new ArrayList<TreeVO>();

    public static <T> List<TreeVO> toTree(List<T> allList) throws NoSuchMethodException {
        return toTree(allList, null, "getName");
    }

    public static <T, S> List<TreeVO> toTree(List<T> allList, List<S> checkedIdList) throws NoSuchMethodException {
        return toTree(allList, checkedIdList, "getName");
    }

    public static <T> List<TreeVO> toTree(List<T> allList, String name) throws NoSuchMethodException {
        return toTree(allList, null, name);
    }

    public static <T, S> List<TreeVO> toTree(List<T> allList, List<S> checkedIdList, String name) throws NoSuchMethodException {
        if (CollectionUtils.isEmpty(allList)) {
            return new ArrayList<>();
        }
        Class<?> clazz = allList.get(0).getClass();
        final Method getId = clazz.getMethod("getId");
        final Method getParentId = clazz.getMethod("getParentId");
        final Method getName = clazz.getMethod(name);
        if (getId == null || getParentId == null || getName == null) {
            return new ArrayList<>();
        }
        //1.实体复制到TreeVO
        List<TreeVO> vos = allList.stream()
                .map(item -> {
                    try {
                        return new TreeVO()
                                .setId(getId.invoke(item).toString())
                                .setParentId(getParentId.invoke(item).toString())
                                .setName(getName.invoke(item).toString())
                                .setChecked(CollectionUtils.isNotEmpty(checkedIdList) && checkedIdList.contains(getId.invoke(item)));
                    } catch (Exception e) {
                    }
                    return null;
                })
                .filter(item -> item != null)
                .collect(Collectors.toList());
        List<TreeVO> treeVOs = vos.stream()
                //2.获取一级菜单
                .filter(item -> SysConstant.ROOT_PARENT_ID.toString().equals(item.getParentId()))
                //3.递归填充子菜单
                .map(item -> fillChildren(item, vos))
                .collect(Collectors.toList());
        return treeVOs;
    }

    private static TreeVO fillChildren(TreeVO treeVO, List<TreeVO> vos) {
        List<TreeVO> childList = vos.stream()
                .filter(item -> item.getParentId().equals(treeVO.getId()))
                .map(item -> fillChildren(item, vos))
                .collect(Collectors.toList());
        if (!childList.isEmpty()) {
            treeVO.setChildren(childList);
        }
        return treeVO;
    }
}
